<?php
	namespace Qzn\Model;
	require_once('./Controller/loginController.php');
	require_once('./Model/database.php');
	require_once('./Model/Hash/hashConfig.php');
	require_once('./Model/Hash/PasswordHash.php');

	class LoginHandler {
		const EVERYTHING_WENT_BETTER_THEN_EXPECTED = 5;
		const USERNAME_DOSNT_EXIST = 6;
		const WRONG_PASSWORD = 7;
		
		public static $m_login = 'loggedIn';
		public static $m_userCat = 'userCat';
		public static $m_userPk = 'userPk';
		private $m_db = null;
		
		public function __construct(Database $db) {
			$this->m_db = $db;
		}
		
		/**
		 * Check if user is logged in
		 * @return boolean
		 */
		public function IsLoggedIn() {
			if (isset($_SESSION[LoginHandler::$m_login])) {
				return true;
			}
			return false;
		}

		/**
		 * @param string $user Username to try
		 * @param string $password Password to try
		 * @return boolean succesfull login
		 */
		public function DoLogin($user, $password, \Qzn\View\LoginView $lw, $isHash) {
			$hash = null;
			$hasher = null;
			$hashConfig = null;
			$currentUser = DatabaseQuery::SelectUsernameWithName($user, $this->m_db);
			$userPk = DatabaseQuery::SelectUserPkWithName($user, $this->m_db);
			
			if ($currentUser == $user) {
				$hash = DatabaseQuery::SelectPasswordWithName($user, $this->m_db);
				
				if (!$isHash) {
					$hashConfig = new \hashConfig();
					$hasher = new \PasswordHash($hashConfig);
					$success = $hasher->CheckPassword($password, $hash);
	
					if (!$success) {
						$tempHash = $this->GetTempPassword($userPk);
						$success = $hasher->CheckPassword($password, $tempHash);
					}
				} else {
					$success = $password === $hash ? true : false;
					
					if (!$success) {
						$tempHash = $this->GetTempPassword($userPk);
						$success = $password === $tempHash ? true : false;
					}
				}
			
				if ($lw->GetRememberMe() || !$lw->TriedToLogin()) {
					$this->SetTempPassword($userPk, $lw);
				}
			
				if ($success) {
					$_SESSION[LoginHandler::$m_login] = $user;
					$_SESSION[LoginHandler::$m_userCat] = DatabaseQuery::SelectUserCatWithName($user, $this->m_db);
					$_SESSION[LoginHandler::$m_userPk] = $userPk;
					return self::EVERYTHING_WENT_BETTER_THEN_EXPECTED;
				} else {
					return self::WRONG_PASSWORD;
				}
			} else {
				return self::USERNAME_DOSNT_EXIST;
			}
		}
		
		/**
		 * @return string Password from database
		 */
		public function GetTempPassword($userPk) {
			$tempPw = DatabaseQuery::SelectTempPassword($userPk, $this->m_db);
			
			if(isset($tempPw[0][0]) && $tempPw[0][1] > time()) {
				return $tempPw[0][0];
			}
			return NULL;
		}

		/**
		 * @param int $userPk
		 * @param LoginView $lw
		 * @return string Password from database
		 */
		public function SetTempPassword($userPk, $lw) {
			DatabaseQuery::DeleteTempPassword($userPk, $this->m_db);
			
			if ($userPk == null) {
				return self::USERNAME_DOSNT_EXIST;
			}
			
			$hashConfig = null;
			$hasher = null;
			$i = 0;
			$pw = $this->RandomPassword(rand(10, 16));
			$date = time() + 2592000;
			
			do {
				$hashConfig = new \hashConfig();
				$hasher = new \PasswordHash($hashConfig);
				$tempPw = $hasher->HashPassword($pw);
				$i++;
			} while (strlen($tempPw) < 20 || $i > 10);
			
			DatabaseQuery::InsertTempPassword($userPk, $tempPw, $date, $this->m_db);
			if ($lw->TriedToReset()) {
				DatabaseQuery::InsertNewPassword($tempPw, $userPk, $this->m_db);
			}
			
			return $pw;
		}
		
		/**
		 * @param LoginView $lw
		 * @return int $userPk
		 */
		public function GetForgettUser(\Qzn\View\LoginView $lw) {
			return DatabaseQuery::SelectUserPkWithName($lw->GetForgettUsername(), $this->m_db);
		}
		
		/**
		 * @param Int $len
		 * @return String randomized
		 */
		public function RandomPassword($len) {
			$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@?#$%^&+=";
			$str = "";
			$size = strlen($chars);
			for($i = 0; $i < $len; $i++) {
				$str .= $chars[rand(0, $size - 1)];
			}
			
			return $str;
		}

		/**
		 * Sets login status to false
		 */
		public function DoLogout() {
			if(isset($_SESSION[LoginHandler::$m_login])) {
				$_SESSION[LoginHandler::$m_login] = null;
				$_SESSION[LoginHandler::$m_userCat] = null;
				$_SESSION[LoginHandler::$m_userPk] = null;
			}
		}
		
		/**
		 * Echo test data
		 * @return boolean
		 */
		public static function Test() {
			$lh = new LoginHandler();
			
			$lh->DoLogOut();
			
			if($lh->IsLoggedIn()) {
				echo "IsLoggedIn eller DoLogout fungerar inte som de ska";
				return false;
			}
			
			if($lh->DoLogin('fel', 'fel')) {
				echo "DoLogin fungerar inte";
				return false;
			}
			
			if(!$lh->DoLogin('ratt', 'rattratt')) {
				echo "DoLogin fungerar inte";
				return false;
			}
			
			if(!$lh->IsLoggedIn()) {
				echo "IsLoggedIn fungerar inte";
				return false;
			}
			
			$lh->DoLogout();
			
			if($lh->DoLogin('ratt', 'fel')) {
				echo "DoLogin med rätt användarnamn och fel lösenord fungerar inte";
				return false;
			}
			
			return true;
		}
	}
?>